-
-
Notifications
You must be signed in to change notification settings - Fork 460
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for bytes formatted images to submit_image and submit_gallery #1891
base: master
Are you sure you want to change the base?
Conversation
Files modified: - submit_image - submit_gallery - _validate_gallery - _upload_media - _read_and_post_media Added new import: - from io import BytesIO Previously, to submit an image to Reddit a filepath to an image stored on the local machine needed to be provided to PRAW to pass through to the Reddit API. This fork changes this behavior by implementing support for bytes objects through the io library. What this means in practical terms: in the original code, the filepath is referenced to retrieve the image file and convert it to bytes format anyway. Now the bytes of an image can be directly passed through while still retaining the original filepath functionality. This means an image retrieved from a server does not need to be downloaded before it can be uploaded: it's String implementation can be passed along to Reddit instead.
Majority of the failures appear to be caused by:
Is the import of new modules permitted? Or does the addition of this module spell death for this PR? |
Let's not add a new dependency as I'll have to take a deeper look at this be just skimming though it, it seems that there is going to be breaking changes. These will need to have a deprecation period. You can tell that you have breaking changes if the existing tests fail without any changes. ETA: this is a very welcome change and I'd love to see this added. |
Alright, sounds great. Would you like me to make changes and resubmit? Or are you going to make the corrections yourself? I haven't contributed to anything open-source before so I'm unsure of guidelines surrounding this sort of thing. |
You got a great start! There is a few options here:
The preferable option is to deprecate the existing parameter, rename it, and have it accept both. This shouldn't be too difficult. Take a look at the existing deprecations for some examples of how it's been done. This should get you started. Let me know if you need any help! |
I think that is common for many libraries, but have a distaste for the variability of the type. I'd prefer to have mutually exclusive keyword arguments |
That is a good point. I do like the idea of adding a new parameter to the media methods (including inline media) for file like objects. My only suggestion is to do |
The original version I wrote actually supported that, though not exactly as you've described. I decided to merge both parameters into one because I wasn't sure what the preferred way of handling the issue of both types being submitted was. So, right now the checklist looks like:
Do I have all that right? |
For the most part yes.
I think
This is still up for discussion.
We need to consider the implications of adding new arguments with the methods that have positional arguments deprecated. i.e., if they become optional they need to be made a keyword-only argument and that might mess with another deprecation. I will help with this point as the code for
For the most part, yes. I think it would be best to also include the inline media, subreddit stylesheet images, and widget images as well (basically anything you can upload an image for). |
|
Made the changes discussed here, though so far only to submit_image and submit_gallery. Both of those work, but because the changes were only made there several other functions now fail because they lack the new parameter (media_fp.) Will need to go through and adjust any functions lacking the parameter so they include it. I removed the PIL import but couldn't figure out how to make use of BinaryIO (or even how to use it, Google was unhelpful.) Instead I decided to make use of the already included dependency of BytesIO, which proved useful enough. With that out of the way, the core of the new implementation works as follows:
Every file format has a unique number of bytes (called a magic number since I guess the 1960s? I just learned about this while putting this together) in its header to indicate what format the file is in. This is the same every time for a format of a given type. PNG files for example contain the following decimal values (converted from hexidecimal): 137 80 78 71 13 10 26 10. Incoming byte values are converted to a list of integers and used as a key for the file_headers dictionary to pull out the file_extension value. Otherwise, media_path has been reverted to its original functionality. Overall I think I'm going to reach a point where I plateau due to not understanding the deeper workings of PRAW--that's probably when I'll need to hand it off to Joel for final touchups--since you offered. Thoughts? |
I don't understand the point of the conversion data inside of PRAW. Anything needed to convert from the PIL image format to BytesIO objects should happen on the caller-side. It looks like you can "save" to a BytesIO file in this way: https://stackoverflow.com/questions/646286/how-to-write-png-image-to-string-with-the-pil |
The idea was to avoid converting as much as possible in this case. For example, the backblaze api returns a regular encoded (hexadecimal) String. I reasoned that this would be ubiquitous among similar services and therefore the simplest type a web browser could return, which I think means it has the best chance of being the format an end-user would make use of when passing to PRAW. Otherwise the file is probably stored on their local machine, so why wouldn't they just supply the filepath at that point? ( Changing it to require an image converted from PIL (or any other library) would not be difficult; it's just a matter of deciding which input format is preferable. ) |
For the There's an example here of saving a PIL file to a BytesIO object: https://stackoverflow.com/a/646297 You'll likely need to seek the BytesIO object back to position 0 after saving: |
So upon further reviewing your last post, I'm a little confused @bboe. The link you provided talks about converting an image to a bytes string, which is already the format the current code accepts--there's no conversion going on inside of PRAW in my latest update to this PR. The current flow would be for someone to utilize the code from your Stack Overflow link, reproduced here:
outside of PRAW, and then they would submit the
(I have already verified that this works using the code in its present state. I've tested it and it posts to Reddit as expected.) Thanks you! |
How do I run tests on PRAW without pushing new code? This is a little too slow and tedious. I'd rather just do all the testing internally before pushing, since it would be both faster and look better in the commit history... |
Should be able to do so by running |
Okay, after some effort I've managed to ensure all the unit tests are passing. A brief summary of what that means:
This handles invalid objects, invalid file headers, and corrupted images being passed to the Let me know what you think. Hopefully it's getting there. |
I'm taking a look at this currently. |
Okay so there are a few things that are odd with our code that I think we should change prior to introducing your change.
Thoughts? |
Here it is
A new exception will likely be triggered in the following Finally, I think that since
|
So after reviewing the code I ultimately decided to throw out my response to point 2 and actually just go with what you recommended @bboe, it ended up being the best way forward in terms of readability and code complexity (or lack thereof!) I've removed the mime checking and replaced it with a user-supplied I've added the following to try and ensure parity with
The idea being to ensure a Currently I'm adding little scraps of documentation inside of |
What @bboe is meaning is to change the existing functionality in PRAW before your changes:
To comment on what was said here, I agree with the first point. The second point, I think
I think the mime type could be removed here because it could be derived from the file name (which is what PRAW currently does). For the third point, I do think there should be a separate function like what @bboe suggested, however, it should require |
I also wanted to add that this PR should also include the methods for uploading images for inline media, emojis, widgets, and the stylesheet. |
So would
And to comment on the inline media/emoji/widget/stylesheet part, I'd like to nail down exactly how this part should work first. It will make copying the functionality over easier once the existing code in the PR has been finalized ( |
To comment on this part:
Could you provide an example of how that would differ from a |
A |
This PR is stale because it has been open for 20 days with no activity. Remove the Stale label or comment or this will be closed in 10 days. |
Going to continue working on this soon. Been otherwise occupied but I haven't abandoned this. |
This PR is stale because it has been open for 20 days with no activity. Remove the Stale label or comment or this will be closed in 10 days. |
Just checking if you're still wanting this to be merged in? Is there anything we could help with? |
I would. I did some work on inline images and that was giving me some
trouble. I'm going to be away until Tuesday but I'll push that up so you
can take a look at it. Thanks!
…On Sun, Oct 23, 2022, 10:47 AM Joel Payne ***@***.***> wrote:
Just checking if you're still wanting this to be merged in? Is there
anything we could help with?
—
Reply to this email directly, view it on GitHub
<#1891 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AKJ6CFLJRQ6ACTARTSOU3E3WEVFZDANCNFSM54XBUT5A>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
This PR is stale because it has been open for 30 days with no activity. Remove the Stale label or comment or this will be closed in 30 days. |
Using a BufferedReader for upload would be a welcome change. |
Feature Summary and Justification
This feature enables a user to upload an image or images each represented as a Bytes Object to Reddit through the submit_image and submit_gallery functions.
For context, my own use-case involves backblaze.com, particularly this function of their API.
To summarize, a successful request to the backblaze API returns images as bytes objects. After looking into PRAW documentation I discovered that I could only submit an image through it by first downloading and saving the file before providing each of the modified functions the filepath(s) of any images I wanted to submit. Given my use case, this would mean I would need my machine to download, save, upload, and then delete any number of images on my system each time I made use of those functions.
These changes mean an object can be pulled in from a foreign API and passed directly to PRAW for uploading. It skips the awkward saving and deleting steps which should save processing time when scaled.
The "image_path" input parameter for both functions has been changed to "image". It still accepts image paths--it's only the name of the input parameter that has changed so as to more clearly indicate that Bytes Objects now work too. In the case of submit_gallery, the input can be mixed. So there could be any number of image paths and Bytes Objects submitted to the same gallery.
References